package cn.shop.gameapi.consumer;

import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.shop.gameapi.model.BuyOrder;
import cn.shop.gameapi.model.GatewaySecret;
import cn.shop.gameapi.model.MerchantGamePartition;
import cn.shop.gameapi.model.Order;
import cn.shop.msgs.OrderMsg;
import cn.shop.utils.enums.OrderStatus;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.concurrent.ThreadPoolExecutor;

import static cn.shop.gameapi.model.SqlContent.SELECT_ORDER;
import static cn.shop.gameapi.model.SqlContent.SELECT_PARTITION;
import static cn.shop.gameapi.model.SqlContent.SELECT_SECRET_IP_UID;

/**
 * @author : 李一涵
 * @date : Created in 2021-12-17 14:19
 * @description :
 */
@RocketMQMessageListener(topic = OrderMsg.TOPIC, consumerGroup = "order-consumer", selectorExpression = OrderMsg.TAG)
public class OrderConsumer implements RocketMQListener<OrderMsg> {

    private static final Logger LOG = LoggerFactory.getLogger(OrderConsumer.class);
    private static final ThreadPoolExecutor EXECUTOR = ExecutorBuilder.create().setCorePoolSize(50).setMaxPoolSize(100).build();

    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Override
    public void onMessage(OrderMsg msg) {
        LOG.info("收到消息:{}", msg);
        EXECUTOR.execute(() -> consumeOrder(msg));
    }

    private void consumeOrder(OrderMsg msg) {
        for (Long id : msg.getIds()) {
            Order order = null;
            try {
                order = jdbcTemplate.queryForObject(SELECT_ORDER, new BeanPropertyRowMapper<>(Order.class), id);
            } catch (Exception ignored) {}
            if (order != null) {
                findPartition(order, msg.getStatus());
            }
        }
    }

    private void findPartition(Order order, OrderStatus status) {
        MerchantGamePartition partition = null;
        try {
            partition = jdbcTemplate.queryForObject(SELECT_PARTITION, new BeanPropertyRowMapper<>(MerchantGamePartition.class), order.getPartitionId());
        } catch (Exception ignored) {}
        if (partition != null) {
            sendOrder(order, partition, status);
        }
    }

    private void sendOrder(Order order, MerchantGamePartition partition, OrderStatus status) {
        GatewaySecret secret = null;
        try {
            secret = jdbcTemplate.queryForObject(SELECT_SECRET_IP_UID, new BeanPropertyRowMapper<>(GatewaySecret.class), partition.getIp(), order.getUid());
        } catch (EmptyResultDataAccessException ignored) {}
        BuyOrder bo = new BuyOrder();
        bo.setPartitionId(order.getPartitionId());
        bo.setId(order.getId());
        if (status == OrderStatus.COMPLETED) {
            bo.setBuyAccount(order.getBuyerAccount());
            bo.setBuyNickname(order.getBuyerName());
            bo.setNum(order.getGoodsNum());
        } else if (status == OrderStatus.REJECTED || status == OrderStatus.SOLD_OUT){
            bo.setBuyAccount(order.getSellerAccount());
            bo.setBuyNickname(order.getSellerName());
            bo.setNum(order.getBackNum());
        } else {
            return;
        }
        bo.setItem(order.getGoods());
        LOG.info("开始发送订单。 order = {}, buyorder = {}", order, bo);
        String url = "http://" + partition.getIp() + ":" + partition.getPort() + "/gateway/api/order/buy";
        try {
            String json = HttpUtil.createPost(url)
                    .header("secret", secret != null ? secret.getSecret() : "")
                    .body(objectMapper.writeValueAsString(Collections.singletonList(bo)))
                    .execute()
                    .body();
            if (StrUtil.isBlank(json)) {
                LOG.error("请求网关订单出错, 秘钥无效");
            } else {
                LOG.info(json);
            }
        } catch (Exception e) {
            LOG.error("请求网关订单出错", e);
        }
    }
}
